package cn.demoncat.util.lang;

import cn.demoncat.util.lang.constant.DateConstant;
import cn.demoncat.util.lang.constant.StringConstant;
import org.apache.commons.lang3.RandomStringUtils;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * ID处理
 *
 * 注：前端JS最多能处理15位数值（最大为9开头的16位数），所以大数ID应使用字符串
 *
 * @author 延晓磊
 *
 * @since 2017年7月10日
 */
public final class IDUtil {

	/**
	 * 根ID-字符串
	 */
	public static final String ROOT_ID = "0";
	/**
	 * 根ID-Long
	 */
	public static final Long ROOT_ID_LONG = 0L;
	/**
	 * 根ID-Integer
	 */
	public static final Integer ROOT_ID_INT = 0;
	/**
	 * 根名称
	 */
	public static final String ROOT_NAME = "全部";
	
	   
	/**
	 * 获取String类型的UUID (32位)
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月10日
	 */
	public static String getUuid(){
		return UUID.randomUUID().toString().replace(StringConstant.BAR,StringConstant.EMPTY);
	}
	
	/**
	 * 获取Long类型的UUID (19位)
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月10日
	 */
	public static String getNumUuid(){
		return String.valueOf(Math.abs(UUID.randomUUID().getLeastSignificantBits()));
	}

	/**
	 * 获取雪花算法生成的ID（生成器通过本地IP分配节点）
	 *
	 * @return 随机ID 18位
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月4日
	 */
	public static String getSnowflakeId() {
		return String.valueOf(SnowflakeId.getByIp());
	}

	/**
	 * 获取雪花算法生成的ID（生成器通过本地IP分配节点）
	 *
	 * 注意：前端只能接收16位数字，应使用String类型
	 *
	 * @return 随机ID 18位
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年9月4日
	 */
	public static long getSnowflakeNumId() {
		return SnowflakeId.getByIp();
	}

	/**
	 * 获取日期ID
	 * 
	 * @param digits	随机数
	 * @return	日期（yyyyMMddHHmmssSSS，17位） + 随机数
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年12月25日
	 */
	public static String getDateId(int digits) {
		if (digits < 1) {
			return LocalDateTime.now().format(DateConstant.NANO_FORMAT_NUM);
		}else {
			return LocalDateTime.now().format(DateConstant.NANO_FORMAT_NUM) + RandomStringUtils.randomNumeric(digits);
		}
	}

	/**
	 * 获取日期ID
	 *
	 * @return	日期（yyyyMMddHHmmssSSS，17位） + 随机数(3位)
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年12月25日
	 */
	public static String getDateId() {
		return getDateId(3);
	}
	
	/**
	 * 获取Long类型的时间(毫秒，共13位)+随机数(位数，通常为2~3位)
	 *
	 * @param digits	随机数位数
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年7月10日
	 */
	public static long getNumTime(int digits ) {
		return Long.parseLong(getTime(digits));
	}

	/**
	 * 获取Long类型的时间(毫秒，共13位)+随机数(3位数)
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月10日
	 */
	public static long getNumTime() {
		return getNumTime(3);
	}
	
	/**
	 * 获取String类型的时间(毫秒，共13位)+随机数(位数，通常为2~4位)
	 * 
	 * @param digits	随机数位数
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年9月10日
	 */
	public static String getTime(int digits) {
		return System.currentTimeMillis() + RandomStringUtils.randomNumeric(digits);
	}
	
	/**
	 * 获取String类型的时间(毫秒，共13位)+随机数(3位数)
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年9月10日
	 */
	public static String getTime() {
		return getTime(3);
	}
	
	/**
	 * 获取时间戳+3位随机数的字符串，再36进制转换并大写
	 * 
	 * @return 10位近唯一的随机字符串(2086年之后为11位)
	 * 
	 * @author 延晓磊
	 */
	public static String getTime36(){
		return LongUtil.to36(getNumTime(3));
	}
	 
	/**
	 * 功能描述：反解getTime36生成的字符串
	 *
	 * @param time36
	 * @return 格式正确返回 生成时的时间戳，解析失败返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年3月29日
	 */
	public static Long checkTime36(String time36){
		//time36为10位，2086年后会变成11位
		if (time36.length() < 10) {
			return null;
		}
		try {
			//解析36进制的Long字符串
			long l = LongUtil.parse36(time36);
			//减去后3位随机数
			String t = l+StringConstant.EMPTY;
			t = t.substring(0, t.length()-3);
			//13位时间戳
			if (t.length() == 13) {
				return Long.valueOf(t);
			}
		} catch (Exception e) {
			return null;
		}
		return null;
	}
	
	/**
	 * 获取时间戳+3位随机数的字符串，再64进制转换
	 * 
	 * @return 
	 * 
	 * @author 延晓磊
	 */
	public static String getTime64(){
		return LongUtil.to64(getNumTime(3));
	}
	 
	/**
	 * 
	 * 功能描述：反解getTime64生成的字符串
	 *
	 * @param time64
	 * @return 格式正确返回 生成时的时间戳，解析失败返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年3月29日
	 */
	public static Long checkTime64(String time64){
		try {
			//解析64进制的Long字符串
			Long l = LongUtil.parse64(time64);
			//减去后3位随机数
			String t = l+StringConstant.EMPTY;
			t = t.substring(0, t.length()-3);
			//13位时间戳
			if (t.length() == 13) {
				return Long.valueOf(t);
			}
		} catch (Exception e) {
			return null;
		}
		return null;
	}

}
